package DB;

import java.util.*;
import java.io.File;
import java.sql.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

//this class holds connection ready to be used
class DBConnectionPool{
	
	static private DBConnectionPool instance = null;
	private String userName;
	private String password;
	private String databaseUrl = "" ;
	private String propertiesFile = "DbProperties.xml";
	
	//the connection pool
	static private Vector<Connection> connections = new Vector<Connection>();
	
	//Singleton
	private DBConnectionPool(){
		databaseUrl = "jdbc:mysql://";
		try{
			String ip = "";
			String name = "";
			String port = "";
			File XmlFile = new File(propertiesFile);
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(XmlFile);
			doc.getDocumentElement().normalize();			
			NodeList nodeLst = doc.getElementsByTagName("DbConnectionProperties");
			Node fstNode = nodeLst.item(0);
		    if (fstNode.getNodeType() == Node.ELEMENT_NODE) {			  
		        Element fstElmnt = (Element) fstNode;
		        NodeList ElmntLst = fstElmnt.getElementsByTagName("DbServerIP");
		        ip =  ElmntLst.item(0).getChildNodes().item(0).getNodeValue();
		        ElmntLst = fstElmnt.getElementsByTagName("DbServerPort");
		        port =  ElmntLst.item(0).getChildNodes().item(0).getNodeValue();
		        ElmntLst = fstElmnt.getElementsByTagName("DbName");
		        name =  ElmntLst.item(0).getChildNodes().item(0).getNodeValue();
		        ElmntLst = fstElmnt.getElementsByTagName("DbUser");
		        userName =  ElmntLst.item(0).getChildNodes().item(0).getNodeValue();
		        ElmntLst = fstElmnt.getElementsByTagName("DbPassword");
		        password =  ElmntLst.item(0).getChildNodes().item(0).getNodeValue();
		        databaseUrl += ip + ":" + port + "/" + name;
		    }
	}
	catch(Exception e){
		
	}
	}
	
	static public DBConnectionPool getInstance(){
		if (instance == null)
			instance = new DBConnectionPool();
		return instance;
	}

	
	private Connection createConnection(){
		
		//try getting connection using reflection and connection manager
		Connection connection = null;
		try{
			//jdbc connection driver
			Class.forName("com.mysql.jdbc.Driver");
			connection = DriverManager.getConnection(databaseUrl, userName, password);
		}
		catch(SQLException sqlException)
		{
			System.err.println("error connecting to DB: " + sqlException);
			return null;
		}
		catch(ClassNotFoundException noClassExecption)
		{
			System.err.println("error retrieving the connector JAR: " + noClassExecption);
			return null;
		}

		return connection;
	}

	//get a connection from the pool, or create one if pool is empty
	// must be synchronized to avoid contention
	public synchronized Connection getConnection(){
		Connection connection = null;
		if(connections.size() > 0){
			//if a connection is available
			connection =  connections.firstElement();
			connections.removeElementAt(0);
			return connection;
		}
		else
			//if not, create connection and later return it to the pool
			return createConnection();		
	}

	//return the connection to the pool
	// must be synchronized to avoid contention
	public synchronized void returnConnection(Connection connection){
		connections.addElement(connection);
	}
}